package main

import (
	"errors"
	"fmt"
)

/*
	函数属于一个包 方法属于一个类型
*/
func main() {
	// result, error := sum(1, -11)
	// if error != nil {
	// 	fmt.Println(error)
	// } else {
	// 	fmt.Println(result)
	// }
	// result2, _ := sum(1, 23)
	// fmt.Println(result2)
	// fmt.Println(sum2(22, 23))
	// fmt.Println("参数总和：", sum3(1, 2, 3, 4, 5, 77))
	// fmt.Println("参数总和：", sum3(22, 28))
	// // 匿名函数
	// result3 := func(a, b int) int {
	// 	return a + b
	// }
	// fmt.Println(result3(2, 10))
	// cl := colsure()
	// fmt.Println(cl())
	// fmt.Println(cl())
	// fmt.Println(cl())
	age := Age(27)
	age.String()
	age.Modify()
	// (&age).Modify()
	age.String()
	// 方法赋值
	sm := Age.String
	sm(age)
}

// func sum(a int,b int) int{
//     return a+b
// }

func sum(a, b int) (int, error) { // 返回类型和return类型要一致
	if a < 0 || b < 0 {
		return 0, errors.New("a或者b不能为负数")
	}
	return a + b, nil
}

func sum2(a, b int) (sum int, err error) {
	if a < 0 || b < 0 {
		return 0, errors.New("a或者b不能为负数")
	}
	sum = a + b
	err = nil
	return
}

/*
	可变参数
	1.函数名称首字母小写代表私有函数，只有在同一个包中才可以被调用；

	2.函数名称首字母大写代表公有函数，不同的包也可以调用；

	3.任何一个函数都会从属于一个包。
	没有用 public、private 这样的修饰符
*/
func sum3(params ...int) int { // 既有普通参数又有可变参数  可变参数放到最后面
	sum := 0
	for _, i := range params {
		sum += i
	}
	return sum
}

// 闭包 在函数内定义的内部函数，可以使用外部函数的变量
// 函数也是一种类型，它也可以被用来声明函数类型的变量、参数或者作为另一个函数的返回值类型。
func colsure() func() int {
	i := 0
	return func() int {
		i++
		return i
	}
}

type Age uint

// 方法String
func (age Age) String() {
	fmt.Println("the age is", age)
}

// 指针类型 指针具有指向原有值的特性 所以修改了原有的值
func (age *Age) Modify() { // 可以是值也可以是指针
	*age = Age(30)
}
